package com.pfzy.ui.activity.voice;

import android.content.Context;
import android.os.Vibrator;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ImageView;

import androidx.core.view.MotionEventCompat;

import com.pfzy.ui.log.MyLog;
import com.pfzy.ui.utils.AudioCacheUtil;
import com.pfzy.ui.utils.UiThread;

import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ImageViewVoiceButton extends ImageView {
    private static final float CANCEL_DISTANCE = 200.0f;
    public static final int CODE_BAD_TIME = 17;
    public static final int CODE_EXCEPTION = 18;
    public static final int CODE_OVER_TIME = 22;
    public static final int CODE_RECODE_END = 32;
    public static final int CODE_RECORD_FAILED = 19;
    public static final int CODE_RECORD_FILE_EXCEPTION = 20;
    public static final int CODE_RECORD_SUCCESS = 21;
    public static final int CODE_START_LEAVE_RELEASE = 24;
    public static final int CODE_START_RECORD = 25;
    public static final int CODE_START_UP_CANCEL = 23;
    //    private static final int FLAG_CLICK_NOT_EFFECT = 1;
    private static final long MAX_LAST_DURATION = 60; // 最大 最后 轴
    //    private static final long MIN_LAST_DURATION = 1;
//    private static final String TAG = "IViewVoiceButton";
    private boolean isCancel;// 取消
    private boolean isDown;
    private boolean isRecordComplete;// 录音已完成
    private RecordListener listener;
    private int mActivePointerId;// 获取触摸点的标识符
    //    private int mFlags;
    private Runnable mTimeRunnable;
    private String path;
    private boolean permissIsBack; // 权限返回
    private boolean permissionReady;
    private long pressDown;// 按下时间
    private long pressUp;// 抬起时间
    private long recordInterval;// 记录间隔
    private ExecutorService singleThreadExecutor;// 单线程线程池
    private int status;
    private Vibrator vibrator;// 手机震动效果(vibrator 震动)

    public interface RecordListener {
        boolean havePermissionsDeny();

        /**
         * 已有录制事件
         */
        void havingRecordingEvent();

        void onBadRecording(int code);

        void onRecordCancel();

        void onRecordComplete(long interval, String filePath, int code);

        void onRecordNormal();

        void onRecordTransformCancel();

        void onRecording(long interval);

        void onStartRecording();
    }

    public ImageViewVoiceButton(Context context) {
        super(context);
        this.isRecordComplete = false;
        this.permissionReady = false;
        this.mActivePointerId = -1;
//        this.mFlags = 0;
        this.singleThreadExecutor = Executors.newSingleThreadExecutor();
        this.mTimeRunnable = new Runnable() {
            @Override
            public void run() {
                if (recordInterval >= ImageViewVoiceButton.MAX_LAST_DURATION) {
                    stopRecord();
                    return;
                }
                recordInterval++;
                UiThread.runUIDelayed(this, 1000L);
                listener.onRecording(recordInterval);
            }
        };
        init();
    }

    public ImageViewVoiceButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.isRecordComplete = false;
        this.permissionReady = false;
        this.mActivePointerId = -1;
//        this.mFlags = 0;
        this.singleThreadExecutor = Executors.newSingleThreadExecutor();
        this.mTimeRunnable = new Runnable() {
            @Override
            public void run() {
                if (recordInterval >= ImageViewVoiceButton.MAX_LAST_DURATION) {
                    stopRecord();
                    return;
                }
                recordInterval++;
                UiThread.runUIDelayed(this, 1000L);
                listener.onRecording(recordInterval);
            }
        };
        init();
    }

    public ImageViewVoiceButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.isRecordComplete = false;
        this.permissionReady = false;
        this.mActivePointerId = -1;
//        this.mFlags = 0;
        this.singleThreadExecutor = Executors.newSingleThreadExecutor();
        this.mTimeRunnable = new Runnable() {
            @Override
            public void run() {
                if (recordInterval >= ImageViewVoiceButton.MAX_LAST_DURATION) {
                    stopRecord();
                    return;
                }
                recordInterval++;
                UiThread.runUIDelayed(this, 1000L);
                listener.onRecording(recordInterval);
            }
        };
        init();
    }

    public ImageViewVoiceButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        this.isRecordComplete = false;
        this.permissionReady = false;
        this.mActivePointerId = -1;
//        this.mFlags = 0;
        this.singleThreadExecutor = Executors.newSingleThreadExecutor();
        this.mTimeRunnable = new Runnable() {
            @Override
            public void run() {
                if (recordInterval >= ImageViewVoiceButton.MAX_LAST_DURATION) {
                    stopRecord();
                    return;
                }
                recordInterval++;
                UiThread.runUIDelayed(this, 1000L);
                listener.onRecording(recordInterval);
            }
        };
        init();
    }

    private void init() {
        Context context = getContext();
        getContext();
        this.vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
    }

    public void setRecordListener(RecordListener listener) {
        this.listener = listener;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        long resultInterval = MAX_LAST_DURATION;

        _logd("onTouchEvent y:" +event.getY());
//        if ((this.mFlags & 1) != 0) {
//            IMLogUtil.i(TAG, "点击 录音按钮 不应该有反应");
//            return true;
//        }
        int action = MotionEventCompat.getActionMasked(event);
        if (event.getAction() != MotionEvent.ACTION_DOWN && this.isCancel) {
            return false;
        }

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (AudioRecorder.getInstance().isRecording()) {
                if (this.listener == null) {
                    return true;
                }
                this.listener.havingRecordingEvent();
                return true;
            } else {
                this.isCancel = false;
                this.permissIsBack = false;
                this.isDown = true;
                this.singleThreadExecutor.execute(new Runnable() {
                    @Override
                    public void run() {
                        permissionReady = listener.havePermissionsDeny();
                        UiThread.runUI(new Runnable() {
                            @Override
                            public void run() {
                                permissIsBack = true;
                                if (permissionReady && isDown) {
                                    startRecording();
                                }
                            }
                        });
                    }
                });
            }
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            this.isDown = false;
        }

        if (!this.permissIsBack) {
            return true;
        }

        if (!this.permissionReady) {
            return false;
        }

        if (this.isRecordComplete || this.status == CODE_RECODE_END) {
            return true;
        }

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                this.mActivePointerId = event.getPointerId(0);
                _logd("[ACTION_DOWN]" + this.path);
                return true;
            case MotionEvent.ACTION_UP:
                event.findPointerIndex(this.mActivePointerId);
                this.mActivePointerId = -1;
                setSelected(false);
                stopCount();
                this.pressUp = System.currentTimeMillis();
                this.status = CODE_START_RECORD;
                if (this.listener != null) {
                    long indexInterval = getPressInterval();
                    this.isRecordComplete = true;
                    if (indexInterval < 1) {
                        AudioRecorder.getInstance().stop();
                        this.listener.onBadRecording(CODE_BAD_TIME);
                    } else if (Math.abs(event.getY()) > CANCEL_DISTANCE) {
                        AudioRecorder.getInstance().stop();
                        this.listener.onRecordCancel();
                    } else {
                        if (indexInterval <= MAX_LAST_DURATION) {
                            resultInterval = indexInterval;
                        }
                        AudioRecorder.getInstance().stop();
                        _logd("[UP事件-结束录音] 文件路径:" + this.path);
                        if (TextUtils.isEmpty(this.path) || !new File(this.path).exists()) {
                            this.listener.onBadRecording(CODE_RECORD_FAILED);
                        } else {
                            this.listener.onRecordComplete(resultInterval, this.path, CODE_RECORD_SUCCESS);
                        }
                    }
                }
                this.isRecordComplete = false;
                return true;
            case MotionEvent.ACTION_MOVE:
                event.findPointerIndex(this.mActivePointerId);
                if (!isSelected()) {
                    setSelected(true);
                }
                _logd("[ACTION_MOVE]" + this.path);
                if (this.recordInterval >= MAX_LAST_DURATION) {
                    if (this.listener == null) {
                        return true;
                    }
                    setSelected(false);
                    stopRecord();
                    return true;
                } else if (this.listener == null) {
                    return true;
                } else {
                    if (Math.abs(event.getY()) > CANCEL_DISTANCE) {
                        if (this.status == CODE_START_LEAVE_RELEASE) {
                            return true;
                        }
                        this.listener.onRecordTransformCancel();
                        this.status = CODE_START_LEAVE_RELEASE;
                        return true;
                    } else if (this.status == CODE_START_UP_CANCEL) {
                        return true;
                    } else {
                        this.listener.onRecordNormal();
                        this.status = CODE_START_UP_CANCEL;
                        return true;
                    }
                }
            case MotionEvent.ACTION_CANCEL:
                this.mActivePointerId = -1;
                setSelected(false);
                return true;
            case MotionEvent.ACTION_OUTSIDE:
            default:
                return true;
            case MotionEvent.ACTION_POINTER_DOWN:
                int pointerIndex = MotionEventCompat.getActionIndex(event);
                this.mActivePointerId = event.getPointerId(pointerIndex);
                return true;
        }
    }

    /**
     * 停止录音
     */
    public void stopRecord() {
        if (this.listener != null) {
            this.isRecordComplete = false;
            if ((this.status != CODE_RECODE_END && this.status != CODE_START_RECORD) || (this.status == CODE_START_RECORD && this.recordInterval >= MAX_LAST_DURATION)) {
                this.status = CODE_START_RECORD;
                UiThread.clearCallBack();
                AudioRecorder.getInstance().stop();
                _logd("[语音超出时长，将自动发送] 文件路径:" + this.path);
                if (TextUtils.isEmpty(this.path) || !new File(this.path).exists()) {
                    this.listener.onBadRecording(CODE_RECORD_FAILED);
                } else {
                    this.listener.onRecordComplete(MAX_LAST_DURATION, this.path, CODE_OVER_TIME);
                }
            }
        }
        cancelRecord();
    }

    /**
     * 停止计数
     */
    public void stopCount() {
        UiThread.removeCallback(this.mTimeRunnable);
    }

    public void startRecording() {
        _logd("开始录音");
        this.recordInterval = 0L;
        this.status = CODE_START_RECORD;
        makeVibration(20);
        this.isRecordComplete = false;
        this.pressDown = System.currentTimeMillis();
        this.path = new File(AudioCacheUtil.getCacheDir(), System.currentTimeMillis() + ".aac").getAbsolutePath();
        try {
            AudioRecorder.getInstance().start(this.path);
            if (this.listener != null) {
                this.listener.onStartRecording();
                this.listener.onRecording(this.recordInterval);
                UiThread.runUIDelayed(this.mTimeRunnable, 1000L);
            }
        } catch (Exception e) {
            e.printStackTrace();
            this.listener.onBadRecording(CODE_RECORD_FAILED);
        }
    }

    /**
     * 设置单击效果
     */
//    public void setClickEffect(boolean effect) {
//        if (effect) {
//            this.mFlags &= -2;
//        } else {
//            this.mFlags |= 1;
//        }
//    }

    public void cancelRecord() {
        this.isCancel = true;
        AudioRecorder.getInstance().stop();
    }

    /**
     * 振动
     * @return
     */
    private void makeVibration(int millisecond) {
        this.vibrator.vibrate(millisecond);
    }

    private long getPressInterval() {
        return getPressInterval(this.pressUp, this.pressDown);
    }

    /**
     * 获取间隔
     * @param up
     * @param down
     * @return
     */
    private long getPressInterval(long up, long down) {
        long index = (up - down) / 1000;
        if (index < 0) {
            return 0L;
        }
        return index;
    }
    private void _logd(String msg) {
        MyLog.logd("录音视图: " + msg);
    }
}
